package com.hsogoo.ultraman.spi;

/**
 * Created by za-huangsaigang on 2018/9/20.
 */

import java.util.List;
import java.util.concurrent.atomic.AtomicReference;


import com.hsogoo.ultraman.Constant;
import org.apache.commons.collections.CollectionUtils;

import com.google.common.collect.Lists;
import com.hsogoo.ultraman.container.ConfigContainer;
import com.hsogoo.ultraman.exceptions.UltramanConfigException;
import com.hsogoo.ultraman.listener.ConfigServerChangeListener;
import com.hsogoo.ultraman.loadbanlance.RoundRobinLoadBalancer;
import com.hsogoo.ultraman.monitor.ConfigChangeMonitor;
import com.hsogoo.ultraman.utils.ConfigMetaUtil;
import com.hsogoo.ultraman.utils.ExceptionUtil;
import com.hsogoo.ultraman.monitor.ZkClient;

import lombok.extern.slf4j.Slf4j;

/**
 * 配置服务的定位器
 */
@Slf4j
public class ConfigServerLocator implements ConfigServerChangeListener {

    private ConfigChangeMonitor configChangeMonitor;
    private AtomicReference<List<String>> configServers;

    public ConfigServerLocator(){
        List<String> initial = Lists.newArrayList();
        configServers = new AtomicReference(initial);
        configChangeMonitor = ConfigContainer.getBean(ConfigChangeMonitor.class);
        configChangeMonitor.monitorConfigServer(this);
        initialize();
    }

    private boolean initialize(){
        try {
            updateConfigServers();
            return true;
        } catch (Throwable ex) {
            //ignore
        }
        return false;
    }

    public String select() {
        if (configServers.get().isEmpty()) {
            updateConfigServers();
        }
        List<String> configServerList = configServers.get();
        return new RoundRobinLoadBalancer(configServerList).select();
    }

    private synchronized void updateConfigServers() {

        try{
            List<String> serverList = configChangeMonitor.getAllConfigServer();
            log.info("update serverList=[{}]", serverList);
            if(CollectionUtils.isNotEmpty(serverList)){
                configServers.set(serverList);
            }else{
                throw new UltramanConfigException("no available config server");
            }
        }catch (Exception ex){
            log.error("get config server list exception", ExceptionUtil.getDetailMessage(ex));
            throw new UltramanConfigException("update config server Excepption", ex);
        }
    }

    @Override
    public void onChange() {
        updateConfigServers();
    }
}
